﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Data.Entity;
using System.Data.Objects;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using UnitOfWork.Validation;
using Eff.Data.Linq;
namespace UnitOfWork
{
    public abstract class RepositoryBase<TModel, TContext>
        where TModel : class
        where TContext : DbContext
    {
        private TContext _dataContext;
        private readonly IDbSet<TModel> _dbset;
        protected RepositoryBase(IDatabaseFactory<TContext> databaseFactory)
        {
            DatabaseFactory = databaseFactory;
            _dbset = DataContext.Set<TModel>();
        }

        protected IDatabaseFactory<TContext> DatabaseFactory
        {
            get;
            private set;
        }

        protected TContext DataContext
        {
            get { return _dataContext ?? (_dataContext = DatabaseFactory.Get()); }
        }
        public virtual void Add(TModel entity)
        {
            //            validationResults = new List<UnitOfWork.Validation.ValidationResult>(10);
            //            var list = GetAttribute<UniquenessAttribute, TModel>(entity);
            //            foreach (var property in list)
            //            {
            //                var value = property.GetValue(entity, null);
            //                if (_dbset.Where(property.Name + "=@0", value).Count() > 0)
            //                    validationResults.Add(new UnitOfWork.Validation.ValidationResult(property.Name, string.Format("{0}已经存在", value)));
            //            }
            //            if (validationResults.Count > 0) return false;
            _dbset.Add(entity);
            //            return true;
        }
        public virtual void Update(TModel entity)
        {
            _dbset.Attach(entity);
            _dataContext.Entry(entity).State = EntityState.Modified;
        }
        public virtual void Delete(TModel entity)
        {
            _dbset.Remove(entity);
        }
        public virtual void Delete(Expression<Func<TModel, bool>> where)
        {
            IEnumerable<TModel> objects = _dbset.Where<TModel>(where).AsEnumerable();
            foreach (TModel obj in objects)
                _dbset.Remove(obj);
        }
        public virtual TModel FindById(long id)
        {
            return _dbset.Find(id);
        }
        public virtual TModel FindById(string id)
        {
            return _dbset.Find(id);
        }
        public virtual IEnumerable<TModel> FindAll()
        {
            return _dbset.ToList();
        }
        public virtual IEnumerable<TModel> Find(Expression<Func<TModel, bool>> where)
        {
            return _dbset.Where(where).ToList();
        }
        public virtual IEnumerable<TModel> Find(string where)
        {
            return _dbset.Where(where).ToList();
        }
        public TModel Get(Expression<Func<TModel, bool>> where)
        {
            return _dbset.Where(where).FirstOrDefault();
        }

        public List<PropertyInfo> GetAttribute<TAttribute, TM>(TM model) where TAttribute : Attribute
        {
            Type type = model.GetType();
            List<PropertyInfo> list = new List<PropertyInfo>(10);
            // 利用反射，遍历这个类中的所有方法 System.Reflection
            foreach (PropertyInfo propertyInfo in type.GetProperties())
            {
                // 通过Attribute类内置的GetCustemAttributes()方法遍历附加在该方法上的所有Attribute.
                foreach (Attribute attr in Attribute.GetCustomAttributes(propertyInfo))
                {
                    // 定位目标Attribute，进行相应的逻辑操作.
                    if (attr.GetType() == typeof(TAttribute))
                        list.Add(propertyInfo);
                }
            }
            return list;
        }
    }
}
